package info.ms.neural.degrade.core;

import info.ms.neural.common.exception.DegradeException;
import info.ms.neural.degrade.IBizDegrade;
import info.ms.neural.degrade.IDegrade;
import info.ms.neural.degrade.runner.IDegradeRunner;
import info.ms.neural.engine.entity.NeuralConf;

/**
 * 服务降级
 * 
 * @author lry
 *
 * @param <REQ>
 * @param <RES>
 */
public class DegradeFactory<REQ, RES> implements IDegrade<REQ, RES> {

	/**
	 * 初始化
	 */
	public void init() throws Throwable {
		
	}

	public RES degrade(NeuralConf conf, IDegradeRunner<REQ, RES> runner, REQ req, IBizDegrade<REQ, RES> bizDegrade) throws Throwable {
		if(!conf.isDegradeEnable()){//服务降级开关关闭,则直接拉起引擎
			return runner.engine(conf, runner, req);
		}
		
		switch (conf.getDegradeType()) {
		case SHIELDING:// 屏蔽降级
			return doDegrade(conf, runner, req);
		case FAULTTOLERANT:// 容错降级
			try {
				return runner.engine(conf, runner, req);
			} catch (Throwable t) {
				return doDegrade(conf, runner, req);// 直接失败,然后执行容错降级
			}
		case BUSINESS:// 业务降级
			return bizDegrade.biz(conf, runner, req);
		default:
			throw new DegradeException("'degradeType' is illegal type.");
		}
	}
	
	/**
	 * 服务降级策略类型
	 * 
	 * @param conf
	 * @param route
	 * @param req
	 * @return
	 */
	private RES doDegrade(NeuralConf conf, IDegradeRunner<REQ, RES> runner, REQ req) throws Throwable{
		switch (conf.getStrategyType()) {
		case NULL:// 返回null降级
			return null;
		case MOCK:// 调用mock降级
			return runner.mock(conf.getNeuralId(), req);
		case EXCEPTION:// 抛异常降级
			throw new DegradeException("Service degradation: throw exception.");
		default:
			throw new DegradeException("The 'strategyType' is illegal type.");
		}
	}
	
	/**
	 * 销毁
	 */
	public void destory() throws Throwable {
		
	}

}
